package com.groupbuying.currency.producer.service.impl;


import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.aliyun.openservices.shade.com.alibaba.fastjson.serializer.SerializerFeature;
import com.groupbuying.currency.producer.connector.SysconfigFeign;
import com.groupbuying.currency.producer.constants.CommonConstants;
import com.groupbuying.currency.producer.constants.CurrencyConstants;
import com.groupbuying.currency.producer.context.FilterContextHandler;
import com.groupbuying.currency.producer.domain.CurrencyCustomerDO;
import com.groupbuying.currency.producer.domain.CurrencyCustomerLogDO;
import com.groupbuying.currency.producer.dto.mq.TokenPayInfoPublishingToMq;
import com.groupbuying.currency.producer.mq.CurrencyMQConfig;
import com.groupbuying.currency.producer.mq.CurrencyMQProducer;
import com.groupbuying.currency.producer.service.CurrencyCustomerLogService;
import com.groupbuying.currency.producer.service.CurrencyCustomerService;
import com.groupbuying.currency.producer.service.CurrencyPayService;
import com.groupbuying.currency.producer.utils.BeanOrMapConvertUtils;
import com.groupbuying.currency.producer.utils.DateUtils;
import com.groupbuying.currency.producer.utils.Object2BigDecimal;
import com.groupbuying.currency.producer.utils.apiresult.ApiResult;
import com.groupbuying.currency.producer.utils.apiresult.ApiResultCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service
public class CurrencyPayServiceImpl implements CurrencyPayService {

    @Autowired
    private CurrencyCustomerService currencyCustomerService;

    @Autowired
    private CurrencyCustomerLogService currencyCustomerLogService;

    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Autowired
    private CurrencyMQProducer currencyMQProducer;

    @Override
    @Transactional
    public ApiResult doPayWithCurrency(Map<String, Object> mapParams) throws Exception {

        Object tempParam = mapParams.get("password");
        String password = tempParam == null ? null : tempParam.toString();
        tempParam = mapParams.get("payId");
        String payId = tempParam == null ? null : tempParam.toString();
        tempParam = mapParams.get("payPrice");
        BigDecimal payPrice = tempParam == null ? null : Object2BigDecimal.getBigDecimal(tempParam);
        tempParam = mapParams.get("opxRuleId");
        String opexRuleId = tempParam == null ? null : tempParam.toString();

        //判断请求参数不为空
        if (StringUtils.isEmpty(password) || StringUtils.isEmpty(opexRuleId) || StringUtils.isEmpty(payId) || payPrice == null) {
            return ApiResult.paramIsNull();
        }

        //检验支付密码
        String customerId = FilterContextHandler.getUserID();
        if(!currencyCustomerService.checkCurrencyPwd(customerId, password)){
            return ApiResult.failure(ApiResultCode.CURRENCY_PAYWORDERROR,"");
        }

        /* 变动积分账户 */
        /* 1、根据opexRuleId获取积分消费规则 */
        Map<String, Object> params = new HashMap();
        params.put("ruleId", opexRuleId);
        params.put("delFlag", CommonConstants.COMMON_FLAG_UNDEL);
        Map ruleMap = sysconfigFeign.getRuleByIdAndDelFlag(params);

        /* 如果获取积分规则为空则抛出异常 */
        if(ruleMap.get("currencyPayDiscount") == null){
            throw new Exception("积分消费打折规则为获取异常!");
        };

        /* 将Obejct转换为BigDecimal进行计算 */
        BigDecimal currencyPayDiscount = Object2BigDecimal.getBigDecimal(ruleMap.get("currencyPayDiscount"));

        /* 2、获取当前积分账户信息，并根据对应积分消费规则计算扣除积分，更新积分账户 */
        CurrencyCustomerDO currencyCustomerDO = currencyCustomerService.get(customerId);
        BigDecimal priceAfterDiscount = payPrice.multiply(currencyPayDiscount);
        BigDecimal useCurrency = currencyCustomerDO.getUseCurrency();
        BigDecimal totalCurrency = currencyCustomerDO.getTotalCurrency();

        /* 如果打折后的积分小于可用积分或总积分，则消费失败，抛出异常“积分不足” */
        if(useCurrency.compareTo(priceAfterDiscount) == -1
            || totalCurrency.compareTo(priceAfterDiscount) == -1){
            throw new Exception("积分不足");
        }

        currencyCustomerDO.setUseCurrency(useCurrency.subtract(priceAfterDiscount));
        currencyCustomerDO.setTotalCurrency(totalCurrency.subtract(priceAfterDiscount));
        currencyCustomerService.update(currencyCustomerDO);

        /* 3、记录积分消费日志（因该日志需入库故同步记录，doPayWithCurrency方法应提现事务性） */
        CurrencyCustomerLogDO currencyCustomerLogDO = new CurrencyCustomerLogDO();
        currencyCustomerLogDO.setLogId(sysconfigFeign.createLogID());
        currencyCustomerLogDO.setActivityId(null);
        currencyCustomerLogDO.setCreateTime(DateUtils.format(new Date(), null));
        currencyCustomerLogDO.setCurrencyCount(priceAfterDiscount);
        /* 碎银流向：01、活动；02、消费 */
        currencyCustomerLogDO.setCurrencySource(CurrencyConstants.CURRENCY_SOURCE_CONSUME);
        /* 碎银变化类型：01：增加：02减少，03：无变化 */
        currencyCustomerLogDO.setCurrencyType(CurrencyConstants.CURRENCY_TYPE_DECREASE);
        currencyCustomerLogDO.setCustomerId(customerId);
        /* 删除标记 1-未删除，0-已删除 */
        currencyCustomerLogDO.setDelFlag(CommonConstants.COMMON_FLAG_UNDEL);
        currencyCustomerLogService.save(currencyCustomerLogDO);

        /* 通知支付中心 */
        Producer producer = currencyMQProducer.getCurrencyMQProducer();

        /* 1、填充发送到支付中心的支付包体 */
        TokenPayInfoPublishingToMq tokenPayInfoPublishingToMq = new TokenPayInfoPublishingToMq();
        tokenPayInfoPublishingToMq.setCurPayLogId(currencyCustomerLogDO.getLogId());
        tokenPayInfoPublishingToMq.setCurPayRecvTime(currencyCustomerLogDO.getCreateTime());
        tokenPayInfoPublishingToMq.setCurPayStatus(CurrencyConstants.CURRENCY_PAY_SUCCESS);
        tokenPayInfoPublishingToMq.setPayCurrency(priceAfterDiscount);
        tokenPayInfoPublishingToMq.setPayId(payId);

        /* 2、发送信息到MQ */
        try {
            Message message = new Message(
                    CurrencyMQConfig.TOPIC,
                    CurrencyMQConfig.TAG_PAY_STATE_SUCCESS,
                    JSON.toJSONString(BeanOrMapConvertUtils.objectToMap(tokenPayInfoPublishingToMq), SerializerFeature.DisableCircularReferenceDetect).getBytes());
            producer.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ApiResult.success();
    }

}
